<template>
  <div class="common">
    <div class="show">
      <show-view/>
    </div>
    <div class="operating">
      <div class="left">
        <my-button v-for="(button,index) in special" :id="index" :button_value="button" @clickButton="clickButton"/>
      </div>
      <div class="right">
        <my-button v-for="(button,index) in basis" :id="index" :button_value="button" @clickButton="clickButton"/>
      </div>
    </div>
  </div>
</template>
<script>
import MyButton from "@/components/MyButton";
import ShowView from "@/components/ShowView";

export default {
  name: "Common",
  components: {MyButton, ShowView},
  data() {
    return {
      answer: '0',
      formula: '0',
      display: '0', // 显示的算式
      is_equal: false,  // 是否点击了等于按钮
      isOperate: false, // 上次是否点击了逻辑操作符
      leftParenthesis: 0, // 左括号的点击次数,用于括号的使用
      operator: '',    // 运算符
      isBinary: false,  // 是否是二进制
      special: [
        "<<", ">>", "~", "cos", "sin", "x!", "Π", "tan", "lg", 'e', "ln", `&#x221A`, "BIN", "Ans", "DEC"
      ],
      basis: [
        '(', ')', '%', 'AC', 7, 8, 9, '/', 4, 5, 6, '*', 1, 2, 3, '-', 0, '.', '=', '+'
      ],
    }
  },
  mounted() {
    // 数学的阶乘函数
    Math.factorial = function (n) {
      let sum = 1;
      for (let i = 2; i <= n; i++) {
        sum *= i;
      }
      return sum;
    }
    // 以10为地的n 的log的值
    Math.getBaseLog = function (y) {
      return Math.log(y) / Math.log(10);
    }
    this.keyDown();
  },
  methods: {
    // 监听键盘
    keyDown() {
      document.onkeydown = (e) => {
        if (e.keyCode >= 96 && e.keyCode <= 105) {
          this.clickButton(e.key, 'Number');
        } else {
          // 小数点
          if (e.keyCode === 110) {
            this.clickButton(e.key, 'Number');
          }
          switch (e.key) {
            case '(': {
              this.clickButton(e.key, 'Operator');
              break;
            }
            case ')': {
              this.clickButton(e.key, 'Operator');
              break;
            }
            case '%': {
              this.clickButton(e.key, 'Operator');
              break;
            }
            case 'Backspace': {
              this.clickButton('AC', 'Remove');
              break;
            }
            case '/': {
              this.clickButton(e.key, 'Operator');
              break;
            }
            case '*': {
              this.clickButton(e.key, 'Operator');
              break;
            }
            case '-': {
              this.clickButton(e.key, 'Operator');
              break;
            }
            case '+': {
              this.clickButton(e.key, 'Operator');
              break;
            }
            case 'Enter': {
              this.clickButton('=', 'Equal');
              break;
            }
            case 'c': {
              // 点击了cos
              this.clickButton('cos', 'Operator');
              break;
            }
            case 's': {
              // 点击了 sin
              this.clickButton('sin', 'Operator');
              break;
            }
            case '!': {
              // 点击了阶乘
              this.clickButton('!', 'Operator');
              break;
            }
            case 'p': {
              // 点击了PI
              this.clickButton('Π', 'Operator');
              break;
            }
            case 't': {
              // 点击了tan
              this.clickButton('tan', 'Operator');
              break;
            }
            case 'l': {
              // 点击了 log
              this.clickButton('log', 'Operator');
              break;
            }
            case 'e': {
              // 点击了 e
              this.clickButton('e', 'Operator');
              break;
            }
            case 'n': {
              // 点击了ln
              this.clickButton('ln', 'Operator');
              break;
            }
            case 'a': {
              // 点击了Ans 上次的答案
              this.clickButton('Ans', 'Operator');
              break;
            }
            case 'b':{
              // 点击了BIN二进制转换
              this.clickButton('BIN','Equal');
              break;
            }
            case 'd':{
              // 点击了DEC十进制转换
              this.clickButton('DEC','Equal');
              break;
            }
            case '<':{
              // 点击<< 左移
              this.clickButton('<<','Equal');
              break;
            }
            case '>':{
              // 点击了>>右移
              this.clickButton('>>','Equal');
              break;
            }
            case '~':{
              // 点击了~取反
              this.clickButton('~','Equal');
              break;
            }
          }
        }
        // 打印键盘对应的code
        // console.log(e.key, e.keyCode);
      }
    },

    clickButton(value, type) {
      switch (value) {
          // ======================特殊数学=========================
        case '~': {
          // 取反操作 先满足是整数
          if (Number.isInteger(Number(this.formula))) {
            // 先转化为数字
            let num = parseInt(this.formula);
            if (this.isBinary) {  // 是二进制，先转为十进制
              // 二进制 先转化为十进制
              num = parseInt(this.formula, 2);
              // this.isBinary = ;
              num = ~num;
              this.$store.state.history_data = this.display;
              // 转化为二进制
              this.formula = num.toString(2);
              this.display = '0B' + num.toString(2);
              // this.isBinary = true;
            } else {
              // 不是二进制
              num = ~num;
              this.formula = num + '';
              this.display = num + '';
            }
            // 右移结果
            this.$store.state.result_data = this.display;
            this.is_equal = true;
            this.isOperate = false;
          }
          break;
        }
        case '>>': {
          // 左移 ， 先满足是整数
          if (Number.isInteger(Number(this.formula))) {
            // 先转化为数字
            let num = parseInt(this.formula);
            if (this.isBinary) {  // 是二进制，先转为十进制
              // 二进制 先转化为十进制
              num = parseInt(this.formula, 2);
              // this.isBinary = ;
              num = num >> 1;
              this.$store.state.history_data = this.display;
              // 转化为二进制
              this.formula = num.toString(2);
              this.display = '0B' + num.toString(2);
              // this.isBinary = true;
            } else {
              // 不是二进制
              num = num >> 1;
              this.formula = num + '';
              this.display = num + '';
            }
            // 右移结果
            this.$store.state.result_data = this.display;
            this.is_equal = true;
            this.isOperate = false;
          }
          break;
        }
        case '<<': {
          // 左移 ， 先满足是整数
          if (Number.isInteger(Number(this.formula))) {
            // 先转化为数字
            let num = parseInt(this.formula);
            if (this.isBinary) {  // 是二进制，先转为十进制
              // 二进制 先转化为十进制
              num = parseInt(this.formula, 2);
              // this.isBinary = ;
              num = num << 1;
              this.$store.state.history_data = this.display;
              // 转化为二进制
              this.formula = num.toString(2);
              this.display = '0B' + num.toString(2);
              // this.isBinary = true;
            } else {
              // 不是二进制
              num = num << 1;
              this.formula = num + '';
              this.display = num + '';
            }
            // 左移操作
            this.$store.state.result_data = this.display;
            this.is_equal = true;
            this.isOperate = false;
          }
          break;
        }
        case 'DEC': {
          // 转为十进制
          // 必须是整数，并且为二进制
          // console.log(Number.isInteger(Number(this.formula)) && this.isBinary)
          if (Number.isInteger(Number(this.formula)) && this.isBinary) {
            // 现在显示框中的算式成为历史
            this.$store.state.history_data = this.display;
            let num = parseInt(this.formula, 2);
            // console.log(num);
            this.formula = num + '';
            this.display = num + '';
            this.$store.state.result_data = this.display;
            this.isBinary = false;
            this.is_equal = true;
            this.isOperate = false; // 没有点击运算符
          }
          break;
        }
        case 'BIN': {
          // 转化为二进制
          // 转化的数字只能是整数  并且不为二进制
          if (Number.isInteger(Number(this.formula)) && !this.isBinary) {
            // 是整数
            let num = parseInt(this.formula);
            this.$store.state.history_data = this.display;
            this.formula = num.toString(2);
            this.display = '0B' + num.toString(2);
            // 转化相当于等于
            this.is_equal = true;
            this.answer = this.display;
            this.$store.state.result_data = this.display;
            this.isOperate = false; // 没有点击运算符
            this.isBinary = true;
          }
          break;
        }
        case '&#x221A': {
          // 开根号
          // if (!this.isBinary) {  // 必须不是二进制
            if (this.formula === '0') {
              this.display = '√('
              this.formula = 'Math.sqrt(';
            } else {
              // 算式不为0时
              if (!this.isOperate) {
                // 上次操作没有点击 逻辑操作
                this.display += '*√(';
                this.formula += '*Math.sqrt(';
              } else {
                // 上次操作 是逻辑操作， 需要添加 √
                this.display += '√(';
                this.formula += 'Math.sqrt(';
              }
            }
            this.leftParenthesis++; // 左括号要加一
            this.isOperate = true;  // 以为有 左括号 所以算是点击了逻辑
            this.is_equal = false;  // 没有点击
          // }

          break;
        }
        case 'ln': {
          // 如果算式为0时
          if (this.formula === '0') {
            this.display = 'ln(';
            this.formula = 'Math.log(';
          } else {
            // 算式不为0时
            if (!this.isOperate) {
              // 上次操作不是 逻辑操作  需要添加 *cos(
              this.display += '*ln(';
              this.formula += '*Math.log(';
            } else {
              // 上次操作是 逻辑操作 需要添加 cos(
              this.display += 'ln(';
              this.formula += 'Math.log(';
            }
          }
          this.leftParenthesis++; // 左括号数量++;
          this.isOperate = true;  // 因为有 右括号, 所以本次视为点击了 逻辑运算符
          this.is_equal = false;
          break;
        }
        case 'e': {
          if (!this.isOperate) {
            if (this.formula === '0') {
              this.display = 'e';
              this.formula = 'Math.E';
            } else {
              this.display += '*e';
              this.formula += '*Math.E';
            }
          } else {
            this.display += 'e';
            this.formula += 'Math.E';
          }
          this.is_equal = false;
          this.isOperate = false;
          break;
        }
        case 'lg': {
          // 如果算式为0时
          if (this.formula === '0') {
            this.display = 'lg(';
            this.formula = 'Math.getBaseLog(';
          } else {
            // 算式不为0时
            if (!this.isOperate) {
              // 上次操作不是 逻辑操作  需要添加 *cos(
              this.display += '*lg(';
              this.formula += '*Math.getBaseLog(';
            } else {
              // 上次操作是 逻辑操作 需要添加 cos(
              this.display += 'lg(';
              this.formula += 'Math.getBaseLog(';
            }
          }
          this.leftParenthesis++; // 左括号数量++;
          this.isOperate = true;  // 因为有 右括号, 所以本次视为点击了 逻辑运算符
          this.is_equal = false;
          break;
        }
        case 'tan': {
          // 如果算式为0时
          if (this.formula === '0') {
            this.display = 'tan(';
            this.formula = 'Math.tan(';
          } else {
            // 算式不为0时
            if (!this.isOperate) {
              // 上次操作不是 逻辑操作  需要添加 *cos(
              this.display += '*tan(';
              this.formula += '*Math.tan(';
            } else {
              // 上次操作是 逻辑操作 需要添加 cos(
              this.display += 'tan(';
              this.formula += 'Math.tan(';
            }
          }

          this.leftParenthesis++; // 左括号数量++;
          this.isOperate = true;  // 因为有 右括号, 所以本次视为点击了 逻辑运算符
          this.is_equal = false;
          break;
        }
        case 'x!': {
          // 点击了x!  阶乘
          if (this.formula !== '0' && !this.isOperate) {
            if (this.display.indexOf('.') === -1) {
              // 不能有小数点
              this.display += '!';//  在屏幕上显示 ！
              this.formula = 'Math.factorial(' + this.formula + ')';
              this.isOperate = true;  // 因为里面有)
              this.is_equal = false;  // 是否点击了 = 等于
            }
          }
          break;
        }
        case 'Π': {
          if (!this.isOperate) {
            if (this.formula === '0') {
              this.display = 'Π';
              this.formula = Math.PI;
            } else {
              this.display += '*Π';
              this.formula += '*' + Math.PI;
            }
          } else {
            this.display += 'Π';
            this.formula += 'Math.PI';
          }
          this.is_equal = false;
          this.isOperate = false;
          break;
        }
        case 'cos': {
          // 如果算式为0时
          if (this.formula === '0') {
            this.display = 'cos(';
            this.formula = 'Math.cos(';
          } else {
            // 算式不为0时
            if (!this.isOperate) {
              // 上次操作不是 逻辑操作  需要添加 *cos(
              this.display += '*sin(';
              this.formula += '*Math.cos(';
            } else {
              // 上次操作是 逻辑操作 需要添加 cos(
              this.display += 'cos(';
              this.formula += 'Math.cos(';
            }
          }
          this.leftParenthesis++; // 左括号数量++;
          this.isOperate = true;
          this.is_equal = false;
          break;
        }
        case 'sin': {
          if (this.formula === '0') {
            // 算式为0，点击sin为sin(
            this.display = 'sin(';
            this.formula = 'Math.sin(';
          } else {
            // 算式不为0
            if (!this.isOperate) {
              // 上次操作不是 逻辑操作  需要添加 *sin(
              this.display += '*sin(';
              this.formula += '*Math.sin(';
            } else {
              // 上次操作是 逻辑操作 需要添加 sin(
              this.display += 'sin(';
              this.formula += 'Math.sin(';
            }
          }
          this.leftParenthesis++; // 左括号数量++;
          // 本次操作的是逻辑
          this.isOperate = true;
          // 本次点击的不是 =
          this.is_equal = false;
          break;
        }
          // ====================基础部分===============================
        case '%': {
          // 取余
          this.formula += value + '';
          this.display += value + '';
          this.is_equal = false;
          this.isOperate = true;  // 更新是否点击了逻辑操作符
          break;
        }
        case '/': {
          // 相除
          this.formula += value + '';
          this.display += value + '';
          this.is_equal = false;
          this.isOperate = true;
          break;
        }
        case '*': {
          // 相乘
          this.formula += value + '';
          this.display += value + ''; // 是否点击了
          this.is_equal = false;  // 是否点击了=
          this.isOperate = true;    // 是否点击了逻辑运算
          break;
        }
        case '-': {
          // 相减
          this.formula += value + ''; // 运行的算式的相减
          this.display += value + '';  // 显示的算式相减
          this.is_equal = false;  // 记录本次操作是否是点击了 =
          this.isOperate = true;  // 记录本次操作是否点击逻辑运算
          break;
        }
        case '+': {
          // 相加
          this.formula += value + '';   // 运行的算式相加
          this.display += value + ''; // 显示的算式相加
          this.is_equal = false;  // 是否点击了 =
          this.isOperate = true;  // 更新是否点击了逻辑操作
          break;
        }
        case '=': {
          // 相等
          // 判断算式中是否还有'('而没有')' 自动不全右括号
          if (this.leftParenthesis !== 0) {
            for (let i = this.leftParenthesis; i > 0; i--) {
              this.display += ')';
              this.formula += ')';
            }
            this.leftParenthesis = 0; // 左括号个数归零
          }
          // 算式为0
          if (this.formula === '0') {
            this.formula = '0';
          }
          this.$store.state.history_data = this.display;  // 显示的历史算式要在这交付
          try {
            // 利用 JS 引擎计算
            this.formula = eval(this.formula) + '';
          } catch (e) {
            this.formula = 'ERROR';
          }
          this.$store.state.result_data = this.display;
          this.is_equal = true;
          // this.answer = this.display;
          // console.log('计算结果：' + this.formula);
          this.isOperate = false;
          this.display = this.formula;
          this.answer = this.formula;
          break;
        }
        case 'AC': {
          // 回退
          if (!this.formula || this.formula === '0' || this.formula === 'ERROR' || isNaN(this.formula)) {
            this.formula = '0';
            this.display = '0';
            this.isOperate = false;
            this.isBinary = false;
          } else {
            this.formula = this.formula.substring(0, this.formula.length - 1);
            this.display = this.display.substring(0, this.display.length - 1);
            if (this.formula.length === 0) {
              this.formula = '0';
            }
          }
          this.is_equal = false;
          // this.display = this.formula;
          // console.log('执行了回退操作');
          // console.log(this.formula);
          break;
        }
        case '(': {
          // 点击了括号
          // console.log(this.formula.lastIndexOf(')'));
          if (!this.isOperate || this.formula.lastIndexOf(')') === this.formula.length - 1) {
            // 上次没有点击操作符
            this.formula += '*(';
            this.display += '*(';
          } else {
            this.formula += value;
            this.display += value;
          }
          this.isOperate = true;
          this.is_equal = false;
          // 开启右括号的使用
          this.leftParenthesis++;
          break;
        }
        case ')': {
          // 点击右括号
          if (this.formula !== '0' && this.leftParenthesis > 0) {
            this.formula += value + '';
            this.display += value + '';
            this.isOperate = true;
            // 关闭左括号的使用权限
            this.leftParenthesis--;
          }
          // this.display = this.formula;
          break;
        }
        case 'Ans': {
          if (this.isOperate) {
            this.formula += this.answer;
            this.display += this.answer;
          } else {
            this.formula = this.answer;
            this.display = this.answer;
          }
          this.is_equal = false;
          this.isOperate = false;
          // this.display = this.formula;
          break;
        }

          // ------------点击数字键盘---------------
        default: {
          // 其他操作
          if (type === 'Number') {
            // 点击数字类型
            if (this.formula === '0' || this.is_equal || this.formula === 'ERROR') {
              if (value === '.') {
                // console.log('点击了小数点:'+value,this.formula)
                this.display += value + '';
                this.formula += value + '';
              } else {
                this.display = value + '';
                this.formula = value + '';
              }
            } else {
              this.display += value + '';
              this.formula += value + '';
            }
            this.is_equal = false;
            this.isOperate = false;
            // 输入数字，说明不是二进制
            this.isBinary = false;
          }
          // this.display = this.formula;
          break;
        }
      }
      this.$store.state.result_data = this.display;
      // eval('44+4*4')
    },
  }

}
</script>

<style scoped lang="css">

.common {
  /*box-shadow: 0 0 5px #bbbbbb;*/
  width: 98%;
  margin: auto;
  margin-top: 14px;
  height: 260px;
  /*display: flex;*/
}

/*.dragTo{*/
/*  width: 100%;*/
/*  height: 20px;*/
/*  !*background-color: red;*!*/
/*  cursor: move;*/
/*}*/
.operating {
  padding-top: 20px;
  display: flex;
}

.left {
  width: 40%;
  display: flex;
  flex-wrap: wrap;
  /*background: blue;*/
}

.right {
  width: 60%;
  /*background: red;*/
  display: flex;
  flex-wrap: wrap;
  justify-content: space-around;
}
</style>